package org.teamh.gui.ingame.effects;

import java.util.ArrayList;

import org.lwjgl.opengl.GL11;
import org.teamh.gui.engine.model.Model;
import org.teamh.gui.engine.model.ModelLoader;
import org.teamh.gui.engine.model.TextureLoader;
import org.teamh.gui.ingame.IngameFunctions;
import org.teamh.logic.datamodel.Creep;
import org.teamh.logic.datamodel.Tower;

/**
 * A singleton class for effect management. It can be accessed in a static way. 
 * @author richard
 *
 */
public class EffectManager {

	private static EffectManager singleton;
	
	private IngameFunctions ingameFunctions;
	
	private ArrayList<Effect> effects;
	private ArrayList<Effect> removal;
	
	private int basicTowerTexture;
	private int slowTowerTexture;
	private int splashTowerTexture;
	private Model rocketModel;
	private Model speedModel;
	private Model ultimateModel;
	
	private EffectManager(IngameFunctions ingameFunctions) {
		this.ingameFunctions = ingameFunctions;
		
		effects = new ArrayList<Effect>();
		removal = new ArrayList<Effect>();
		
		initTextures();
	}
	
	private void initTextures() {
		basicTowerTexture = TextureLoader.loadTexture("res/img/shots/canon_ball.png");
		splashTowerTexture = TextureLoader.loadTexture("res/img/shots/splash_samen.png");
		slowTowerTexture = TextureLoader.loadTexture("res/img/shots/snow_snow2.png");
		rocketModel = ModelLoader.getModel("res/img/shots/rocket.obj");
		speedModel = ModelLoader.getModel("res/img/shots/laser.obj");
		ultimateModel = ModelLoader.getModel("res/img/shots/ultimate.obj");
	}
	
	public void addEffectFiredOn(String towerID, String creepID) {
		Tower tower = ingameFunctions.getGui().getStart().getLogic().getManager().getTower(towerID);
		Creep creep = ingameFunctions.getGui().getStart().getLogic().getManager().getCreep(creepID);
		
		if(creep == null || tower == null || tower.getCell() == null) {
			return;
		}
		
		float fromX = tower.getCell().getWorldX();
		float fromY = 3f / 16;
		float fromZ = tower.getCell().getWorldY();
		
		float toX = creep.getWorldX();
		float toY = 1f / 22;
		float toZ = creep.getWorldZ();
		
		if(tower.getType().equalsIgnoreCase("basic")) {
			addEffect(new TextureShot(fromX, fromY, fromZ, toX, toY, toZ, basicTowerTexture));
		} else if(tower.getType().equalsIgnoreCase("slow")){
			addEffect(new TextureShot(fromX, fromY, fromZ, toX, toY, toZ, slowTowerTexture));
		} else if(tower.getType().equalsIgnoreCase("splash")){
			addEffect(new TextureShot(fromX, fromY, fromZ, toX, toY, toZ, splashTowerTexture));
		} else if(tower.getType().equalsIgnoreCase("rocket")){
			fromY = 1f / 16;
			addEffect(new LinearShot(fromX, fromY, fromZ, toX, toY, toZ, rocketModel));
		} else if(tower.getType().equalsIgnoreCase("speed")){
			fromY = 1.5f / 16;
			addEffect(new LinearShot(fromX, fromY, fromZ, toX, toY, toZ, speedModel));
		} else if(tower.getType().equalsIgnoreCase("ultimate")){
			fromY = 3f / 20;
			addEffect(new UltimateEffect(fromX, fromY, fromZ, toX, toY, toZ, creep, ultimateModel));
		} else {
			//should not happen
		}
	}
	
	public void addEffect(Effect effect) {
		if(effect != null) {
			effects.add(effect);
		}
	}
	
	public void render(float timeElapsed) {
		boolean lighting = GL11.glGetBoolean(GL11.GL_LIGHTING);
		GL11.glEnable(GL11.GL_ALPHA_TEST);
		GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f);
		GL11.glDisable(GL11.GL_LIGHTING);
		
		for(Effect e: effects) {
			e.render(timeElapsed);
		}
		
		removeEffects();
		
		if(lighting) {
			GL11.glEnable(GL11.GL_LIGHTING);
		}
	}
	
	private void removeEffects() {
		for(Effect e: removal) {
			effects.remove(e);
		}
		
		removal.clear();
	}
	
	public void removeEffect(Effect effect) {
		if(effect != null) {
			removal.add(effect);
		}
	}
	
	public IngameFunctions getIngameFunctions() {
		return ingameFunctions;
	}
	
	public static EffectManager create(IngameFunctions ingameFunctions) {
		if(singleton == null) {
			singleton = new EffectManager(ingameFunctions);
		}
		
		return singleton;
	}
	
	public static EffectManager get() {
		return singleton;
	}
	
	public void clear() {
		effects.clear();
	}
}